package web;

import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import db.ClubAdministratorRepository;
import db.SystemAdministratorRepository;
import db.UserRepository;
import domain.ClubAdministrator;
import domain.SystemAdministrator;
import domain.User;
import domain.Club;

/**
 * 系统主页控制类
 * 
 * @author zdc
 * @author zhelang
 * @version v1.0
 */
@Controller // 控制定义
@RequestMapping("/") // 相应web路径
public class HomeController {

	@Autowired // 自动注入资源
	private UserRepository userRepository;
	@Autowired
	private ClubAdministratorRepository clubAdministratorRepository;
	@Autowired
	private SystemAdministratorRepository systemAdministratorRepository;

	/**
	 * 渲染系统首页。
	 * <p>
	 * 此方法处理根URL的GET请求，并返回应用程序的首页视图名称。
	 * 实际的JSP页面位置由{@link org.springframework.web.servlet.view.InternalResourceViewResolver}解析，
	 * 根据其配置的前缀和后缀来确定。默认情况下，它会寻找位于`/WEB-INF/views/`目录下的`home.jsp`文件。
	 * </p>
	 *
	 * @return 系统首页视图名称 home
	 */
	@RequestMapping(method = GET)
	public String home(@CookieValue(value = "userId", defaultValue = "-1") int userId, HttpSession session) {
		// 如果当前用户已登录，在不同窗口访问时则会自动登录
		if(userId != -1) {
			User user = userRepository.findOne(userId);
			session.setAttribute("user", user);
			return "redirect:/user";
		}
		return "home";
	}

	/**
	 * 渲染登录表单页面
	 * 
	 * @return 登录表单页面的视图名称 loginForm
	 */
	@RequestMapping(value = "/login", method = GET)
	public String showLoginForm(@CookieValue(value = "userId", defaultValue = "-1") int userId, HttpSession session) {
		// 如果当前用户已登录，在不同窗口访问时则会自动登录
		if(userId != -1) {
			User user = userRepository.findOne(userId);
			session.setAttribute("user", user);
			return "redirect:/user";
		}
		return "loginForm";
	}

	/**
	 * 处理登录请求。
	 *
	 * 根据用户角色验证登录凭证，并重定向到相应的页面。如果登录失败，
	 * 用户将被重定向回登录表单，并显示错误消息。
	 *
	 * @param username 用户名参数，不能为空。
	 * @param password 密码参数，不能为空。
	 * @param role 用户角色参数，用于区分不同类型的用户。
	 * @param session HttpSession对象，用于存储登录后的用户信息。
	 * @param model Model对象，用于向视图添加属性。
	 * @return 成功登录后的重定向路径，或返回登录表单视图的名称。
	 */
	@RequestMapping(value = "/login", method = POST)
    public String processLogin(@RequestParam(value = "username", defaultValue = "") String username,
							   @RequestParam(value = "password", defaultValue = "") String password,
							   @RequestParam(value = "role", defaultValue = "") String role,
							   HttpSession session, HttpServletResponse response, Model model) {
		Boolean loginError = false;
		switch (role) {
			case "user":

				User user = userRepository.findByUserName(username, password);
				if (user != null) {
					session.setAttribute("user", user);

					// 创建一个 Cookie来存储用户 ID
					Cookie userIdCookie = new Cookie("userId", String.valueOf(user.getUserID()));
					userIdCookie.setPath("/");
					userIdCookie.setMaxAge(60 * 60 * 2); // 设置Cookie有效期为 2小时
					// 添加Cookie到响应中
					response.addCookie(userIdCookie);

					model.addAttribute("loginError", loginError);
					return "redirect:/user";
				}
				break;
			case "club_admin":
				ClubAdministrator clubAdmin = clubAdministratorRepository.findByUserName(username, password);
				if (clubAdmin != null) {
					Club club = null;
					try {
						// 系统管理员删除社团时，没删除对应的管理员
						club = clubAdministratorRepository.findClubByAdminID(clubAdmin.getClubAdminID());
					} catch (Exception e) {
						model.addAttribute("loginError", true);
						return "loginForm";
					}
					session.setAttribute("clubAdministrator", clubAdmin);
					session.setAttribute("club", club);
					model.addAttribute("loginError", loginError);
					return "redirect:/clubAdministrator/index";
				}
				break;
			case "system_admin":
				SystemAdministrator systemAdmin = systemAdministratorRepository.findByUserName(username, password);
				if (systemAdmin != null) {
					session.setAttribute("systemAdministrator", systemAdmin);
					model.addAttribute("loginError", loginError);
					return "redirect:/systemAdministrator/index";
				}
				break;
		}
		model.addAttribute("loginError", true);
		return "loginForm";
	}

	/**
	 * 渲染用户注册表单页面。
	 *
	 * 此方法处理针对"/register"路径的GET请求，向模型添加一个新的User对象实例，
	 * 并返回一个用于显示用户注册表单的视图名称。
	 *
	 * @param model Spring的Model对象，用于将数据传递给视图。
	 * @return 注册表单页面的视图名称 "registerForm"。
	 */
	@RequestMapping(value = "/register", method = GET)
	public String showRegistrationForm(Model model) {

		model.addAttribute(new User());
		return "registerForm";
	}

	/**
	 * 处理用户注册信息的提交。
	 *
	 * 用户提交的注册信息会经过验证。若验证失败，则用户会被提示错误信息，
	 * 并重新填写注册表单。如果验证成功，用户信息将被保存到数据库，
	 * 并且用户会被重定向到用户信息页面。
	 *
	 * @param user       User对象，包含了用户填写的注册信息。
	 * @param confirmPassword 确认密码字段，用于与用户密码比较以验证是否匹配。
	 * @param errors     错误对象，用于存储表单验证结果。
	 * @param session    HttpSession对象，可以用于保存用户会话信息。
	 * @param model      Model对象，用于向视图添加属性。
	 * @return 注册表单页面的视图名称 "registerForm"，或者在成功注册后的重定向路径。
	 */
	@RequestMapping(value = "/register", method = POST)
	public String processRegistration(@Valid User user,
									  @RequestParam(value = "confirmPassword") String confirmPassword,
									  Errors errors, HttpSession session, Model model) {
		boolean registerError = false;
		// 注册验证：用户必须完整填写注册表单 || 不允许账号重复 || 确认密码和密码必须相同
		if(errors.hasErrors()) {
			model.addAttribute("registerResult", "注册失败，请重新填写！");
			registerError = true;
		}
		if(userRepository.findByUserName(user.getUsername()) != null) {
			model.addAttribute("registerResult", "注册失败，账号重复！");
			registerError = true;
		} else if(!confirmPassword.equals(user.getPassword())) {
			model.addAttribute("registerResult", "注册失败，两次密码输入不一致！");
			registerError = true;
		}

		// 注册成功，向数据库添加用户
		if(!registerError) {
			model.addAttribute("registerResult", "注册成功！");
			userRepository.save(user);
		}
		model.addAttribute("registerError", registerError);
		return "registerForm";
	}

	/**
	 * 处理用户的注销操作。
	 *
	 * 此方法注销用户，移除会话中的用户信息，并使当前会话失效。
	 * 注销后，用户将被重定向到网站的首页。
	 *
	 * @param session HttpSession对象，用于获取和操作当前用户的会话。
	 * @return 重定向到网站首页的路径。
	 */
	@RequestMapping(value = "/logout", method = GET)
	public String logout(HttpSession session, HttpServletResponse response) {
		session.removeAttribute("user");
		// 销毁 Session
		session.invalidate();

		// 销毁名为 "userId"的 Cookie
		Cookie userIdCookie = new Cookie("userId", "-1");
		userIdCookie.setPath("/");
		userIdCookie.setMaxAge(0); // 设置为立即过期
		response.addCookie(userIdCookie); // 添加到响应中以覆盖旧的Cookie

		// 退出登录，重定向到主页
		return "redirect:/";
	}

}

